<?php

if (!defined('IN_BIC')) {
    die('非法数据库访问来源!');
}

/**
 *
 * @package Bic
 * @author Bic
 * @version $Id: BicSqli.php 2009年6月6日 09时53分11秒
 * @copyright (c) 2005 Bic
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 *
 * Minimum Requirement: PHP 5.0.1
 */
class Bic_Db_Drivers_Mysqli extends Bic_Base {

    public $_dbhost = NULL;
    public $_dbuser = NULL;
    public $_dbpassword = NULL;
    public $_dbname = NULL;
    public $_dbport = NULL;
    public $_queries = array();
    public $_nums = 0;
    private $_link = NULL;
    static $_instance = array();

    private function __construct() {
        $this->_dbhost = DB_HOST;
        $this->_dbuser = DB_USER;
        $this->_dbpassword = DB_PASSWORD;
        $this->_dbname = DB_NAME;
        $this->_dbport = (DB_PORT == '') ? 3306 : DB_PORT;
        $this->_link = new mysqli($this->_dbhost, $this->_dbuser, $this->_dbpassword, $this->_dbname, $this->_dbport);
        if (mysqli_connect_errno()) {
            exit("数据库链接失败:<br />" . mysqli_connect_error());
        }
        $this->justQuery("SET NAMES UTF8");
    }

    private function __clone() {
        
    }

    public static function getInstance($key) {

        $keyMd5 = md5($key == '' ? 'default' : $key);
        if (empty(self::$_instance[$keyMd5])) {
            self::$_instance[$keyMd5] = new self();
        }
        if (!(self::$_instance[$keyMd5] instanceof self)) {
            throw new Bic_Exception('实例化的类不属于:' . __CLASS__);
        }
        return self::$_instance[$keyMd5];
    }

    /**
     * 执行SQL语句并返回执行结果
     *
     * @param string $sql	SQL语句
     * @return result
     */
    function justQuery($sql) {
        $this->_queries[] = $sql;
        return $this->_link->query($sql);
    }

    /**
     * 获取第一条数据
     *
     * @param string $sql	:sql语句
     * @param string $returnType	Object:以对象数据返回|Array:以关联数组或数字数组数据 返回|Assoc关联|Row数字数组
     * @return Array|Object
     */
    function firstRow($sql, $returnType = 'Array') {
        if (!($res = $this->justQuery($sql))) {
            return null;
        }
        switch ($returnType) {
            case 'Object':
                $operator = 'fetch_object';
                //$ret=$res->fetch_object();
                break;
            case 'Array':
                $operator = 'fetch_array';
                //$ret=$res->fetch_array();
                break;
            case 'Assoc':
                $operator = 'fetch_assoc';
                //$ret=$res->fetch_assoc();
                break;
            case 'Row':
                $operator = 'fetch_row';
                //$ret=$res->fetch_row();
                break;
            default:
                $operator = 'fetch_' . strtolower($returnType);
                break;
        }
        $ret = $res->$operator();
        $res->free();
        return $ret;
    }

    function result($sql, $fields) {
        if (!($res = $this->justQuery($sql))) {
            return null;
        }
        $ret = $res->fetch_array();
        $arr = explode(',', $fields);
        foreach ($arr as $v) {
            $new[$v] = $ret[$v];
        }
        $res->free();
        return $new;
    }

    /**
     * 执行SQL语句
     *
     * @param string $sql	SQL语句
     * @param string $returnType	Object:以对象数据返回|Array:以关联数组或数字数组数据 返回|Assoc关联|Row数字数组
     * 								当为Object时,只有数据单元为Object.返回的值,仍为数组
     * @param bool $return	是否返回数据
     * @param bool $batch	批处理[没完成]
     * @return Array
     */
    function query($sql, $returnType = 'Array', $return = true, $batch = false) {
        $new = null;
        switch ($batch) {
            case false:
                if (!($res = $this->justQuery($sql))) {
                    return null;
                }
                switch ($returnType) {
                    case 'Object':
                        $operator = 'fetch_object';
                        //$ret=$res->fetch_object();
                        break;
                    case 'Array':
                        $operator = 'fetch_array';
                        //$ret=$res->fetch_array();
                        break;
                    case 'Assoc':
                        $operator = 'fetch_assoc';
                        //$ret=$res->fetch_assoc();
                        break;
                    case 'Row':
                        $operator = 'fetch_row';
                        //$ret=$res->fetch_row();
                        break;
                    default:
                        $operator = 'fetch_' . strtolower($returnType);
                        break;
                }

                if ('' != ($res)) {
                    while (!is_null($ret = $res->$operator())) {
                        $new[] = $ret;
                    }
                }

                break;
            case true:
            default:
                break;
        }
        if ('' != ($res)) {
            $res->free();
        }

        return $return == true ? $new : null;
    }

    /**
     * 爱影响的数据条数
     *
     * @return int
     */
    public function affectedRows() {
        return $this->_link->affected_rows;
    }

    public function errno() {
        return $this->_link->errno;
    }

    /**
     * 最后一次查询错误信息
     *
     * @return unknown
     */
    public function error() {
        return $this->_link->error;
    }

    /**
     * 查询结果数
     *
     * @param string $sql
     */
    public function numRows($sql) {
        return $this->justQuery($sql)->num_rows;
    }

    /**
     * 字段数
     *
     * @param string $sql
     */
    public function numFields($sql) {
        return $this->justQuery($sql)->field_count;
    }
    
    public function getColumns($table){
        return $this->query("desc {$table}");
    }

    /**
     * 最后插入数据的id
     *
     * @return int
     */
    public function insertId() {
        return $this->_link->insert_id;
    }

    public function version() {
        return $this->_link->server_info;
    }

    public function close() {
        $this->_link->close();
    }

    function __destruct() {
        $this->_link->close();
    }

}

?>
